//
//  Multithreaded relay
//

package main

import (
	"fmt"
	"os"
	"zmq"
)

var errch = make(chan os.Error)


func step1(context *zmq.Context) os.Error {
	xmitter, err := context.Socket(zmq.PAIR)
	if err != nil {
		return err
	}
	defer xmitter.Close()

	err = xmitter.Connect("inproc://step2")
	if err != nil {
		return err
	}
	err = xmitter.Send([]byte("READY"), 0)
	if err != nil {
		return err
	}
	return nil
}

func step2(context *zmq.Context) os.Error {
	receiver, err := context.Socket(zmq.PAIR)
	if err != nil {
		return err
	}
	defer receiver.Close()

	err = receiver.Bind("inproc://step2")
	if err != nil {
		return err
	}

	go func() {
		errch <- step1(context)
	}()

	_, err = receiver.Recv(0)
	if err != nil {
		return err
	}

	xmitter, err := context.Socket(zmq.PAIR)
	if err != nil {
		return err
	}
	defer xmitter.Close()

	err = xmitter.Connect("inproc://step3")
	if err != nil {
		return err
	}
	err = xmitter.Send([]byte("READY"), 0)
	if err != nil {
		return err
	}
	return nil
}

func zmq_main() os.Error {
	context, err := zmq.Init(0)
	if err != nil {
		return err
	}
	defer context.Close()

	receiver, err := context.Socket(zmq.PAIR)
	if err != nil {
		return err
	}

	err = receiver.Bind("inproc://step3")
	if err != nil {
		return err
	}
	defer receiver.Close()

	go func() {
		errch <- step2(context)
	}()

	_, err = receiver.Recv(0)
	if err != nil {
		return err
	}
	return nil
}

func main() {
	fmt.Println("Multithreaded relay")
	exit := make(chan bool)
	go func() {
		for {
			err := <-errch
			if err != nil {
				fmt.Println(err)
				os.Exit(2)
			}
		}
	}()
	go func() {
		err := zmq_main()
		if err != nil {
			errch <- err
		} else {	
			fmt.Println("Test successful")
			exit <- true
		}
	}()
	<-exit
}
